package com.fanshuai.bootstrap;

import com.fanshuai.config.EndPoint;
import com.fanshuai.net.handler.ProxyHandler;
import com.fanshuai.net.proxy.Proxy;
import com.fanshuai.net.proxy.impl.ProxyClient;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ProxyServer {

    public static void start(int port) {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup ioGroup = new NioEventLoopGroup();

        try {
            EndPoint.init();
            serverBootstrap.group(bossGroup, ioGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel channel) throws Exception {
                            ChannelPipeline pipeline = channel.pipeline();
                            pipeline.addLast(
                                    new HttpServerCodec(), new HttpObjectAggregator(65536), new ChunkedWriteHandler());

                            String server = EndPoint.getServer();
                            Proxy proxy = new ProxyClient(server, channel);
                            pipeline.addLast(new ProxyHandler(proxy));
                        }
                    });

            ServerSocketChannel channel = (ServerSocketChannel) serverBootstrap.bind(port).sync().channel();
            log.info("netty proxy server started, channel={}", channel);
            channel.closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            ioGroup.shutdownGracefully();
        }
    }
}
